package m.meiweitech.com.rocket

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.core.app.ActivityCompat
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import m.meiweitech.com.rocket.entities.MachineInfoList
import m.meiweitech.com.rocket.util.MacCheckUtil
import m.meiweitech.com.rocket.util.SpUtil
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.inuker.bluetooth.library.connect.listener.BluetoothStateListener
import com.inuker.bluetooth.library.search.SearchRequest
import com.inuker.bluetooth.library.search.SearchResult
import com.inuker.bluetooth.library.search.response.SearchResponse
import com.orhanobut.logger.Logger
import cpcl.PrinterHelper
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import m.meiweitech.com.rocket.app.App
import m.meiweitech.com.rocket.entities.FlutterDeviceInfo
import m.meiweitech.com.rocket.entities.MachineInfoList
import m.meiweitech.com.rocket.entities.PermissionRequestEntity
import m.meiweitech.com.rocket.entities.PrinterType
import m.meiweitech.com.rocket.ext.observeObject
import m.meiweitech.com.rocket.ext.postObject
import m.meiweitech.com.rocket.helper.BlueConnectStatusListener
import m.meiweitech.com.rocket.helper.KeyHelper
import m.meiweitech.com.rocket.helper.PipeHelper
import m.meiweitech.com.rocket.util.BluetoothClientUtil
import permissions.dispatcher.PermissionRequest
import permissions.dispatcher.ktx.PermissionsRequester
import permissions.dispatcher.ktx.constructPermissionsRequest
import org.json.JSONObject
import java.io.File
import java.util.concurrent.TimeoutException
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import m.meiweitech.com.rocket.entities.PrinterEntity
import java.lang.reflect.Type


class MainActivity : FlutterFragmentActivity() {

    /**
     * 是否显示设备列表
     */
    private var mIsShowDeviceList = false

    /**
     * 搜索到设备的集合
     */
    private var mDevices: MutableList<SearchResult> = mutableListOf()

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var androidToFlutterChannel: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var mainPageFlutterChannel: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var asOrderPageFlutterChannel: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var searchDevicePageChannel: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var deviceDetailPageFlutter: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var scrollFlutterChannel: MethodChannel

    /**
     * android向Flutter发送消息的通道
     */
    lateinit var dismissChannel: MethodChannel

    /**
     * 第三方权限处理的api
     */
    private lateinit var mPermissionsRequester: PermissionsRequester

    /**
     * 权限统一处理的实体类
     */
    private var mPermissionRequestEntity: PermissionRequestEntity? = null

    /**
     * 是否已经开启轮询
     */
    private var mIsPollSustainCheckConnect = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        addLifecycleOwner()
        bluetoothOpenStateListener()
    }


    /**
     * 在有权限的情况下持续尝试连接最后一次连接过的打印机,判断设备是否已经连接
     */
    private fun sustainCheckConnect() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_CONNECT
            ) != PERMISSION_GRANTED) {
            Logger.i("是否具备Manifest.permission.BLUETOOTH_CONNECT权限 = ${ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PERMISSION_GRANTED}")
            return
        }
            mIsPollSustainCheckConnect = true
            lifecycleScope.launch {
                withContext(context = Dispatchers.IO) {
                    delay(2000)
                }
                val isConnect = MacCheckUtil.isBtConDeviceByMac(SpUtil.MMKV_mac)
                val bluetoothAdapter =
                    (getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
                val bluetoothDevice = bluetoothAdapter.getRemoteDevice(SpUtil.MMKV_mac)
                val series = if (bluetoothDevice.name == null) {
                    MachineInfoList[0].series
                } else {
                    MachineInfoList.firstOrNull {
                        bluetoothDevice.name.contains(it.series)
                    }.run {
                        this?.series ?: MachineInfoList[0].series
                    }
                }
                BlueConnectStatusListener.notifyStatusAll(
                    this@MainActivity,
                    FlutterDeviceInfo(
                        bluetoothDevice,
                        series,
                        isConnect
                    )
                )
                sustainCheckConnect()
            }
    }

    /**
     * 接收消息事件
     */
    private fun addLifecycleOwner() {
        //统一权限处理
        observeObject(KeyHelper.PERMISSION_REQUEST_KEY, this, PermissionRequestEntity::class.java) {
            mPermissionRequestEntity = this
            constructPermissionsRequest(
                *permissions,
                onShowRationale = ::onShowRationale,
                onPermissionDenied = ::onPermissionDenied,
                onNeverAskAgain = ::onNeverAskAgain,
                requiresPermission = ::requiresPermission
            ).also {
                mPermissionsRequester = it
                mPermissionsRequester.launch()
            }
        }

        //权限已获取,执行权限事件
        observeObject(javaClass.name, this, PermissionRequestEntity::class.java) {
            mPermissionRequestEntity = this
            if (action == KeyHelper.LOCATION_ACTION_4) {
                if (!BluetoothClientUtil.mBluetoothClient.isBluetoothOpened) {
                    BluetoothClientUtil.mBluetoothClient.openBluetooth()
                } else {
                    asOrderPageFlutterChannel.invokeMethod(KeyHelper.TO_PRINTER_DETAIL_PAGE_CHANNEL, null)
                    mPermissionRequestEntity = null
                }
            } else if (action == KeyHelper.LOCATION_ACTION_5) {
//                    if (!mBluetoothClient.isBluetoothOpened) {
//                        mBluetoothClient.openBluetooth()
//                    } else {
//                        if (MacCheckUtil.isBtConDeviceByMac(SpUtil.MMKV_mac)) {
//                            printAll()
//                        } else {
//                            nav(R.id.action_printSimpleSaleFragment_to_printerFragment)
//                        }
//                        mPermissionRequestEntity = null
//                    }
            } else if (action == KeyHelper.LOCATION_ACTION_6) {
//                    if (!mBluetoothClient.isBluetoothOpened) {
//                        mBluetoothClient.openBluetooth()
//                    } else {
//                        if (MacCheckUtil.isBtConDeviceByMac(SpUtil.MMKV_mac)) {
//                            print(mAdapter.getViewByPosition(mPermissionRequestEntity!!.any as Int,R.id.clPrintContainer)!!)
//                        } else {
//                            nav(R.id.action_printSimpleSaleFragment_to_printerFragment)
//                        }
//                        mPermissionRequestEntity = null
//                    }
            }else if(action == KeyHelper.BLUETOOTH_CONNECT){
                BlueConnectStatusListener.setBinaryMessenger()
                sustainCheckConnect()
            }
        }
    }

    /**
     * 跳转打印页模板
     */
    private fun connectOrDetail() {
        if (BluetoothClientUtil.mBluetoothClient.isBluetoothOpened) {
            asOrderPageFlutterChannel.invokeMethod(KeyHelper.TO_PRINTER_DETAIL_PAGE_CHANNEL, null)
        } else {
            BluetoothClientUtil.mBluetoothClient.openBluetooth()
        }
    }

    /**
     * 第一次请求权限时被拒绝时调用,向用户解释为什么需要调用该权限
     */
    private fun onShowRationale(request: PermissionRequest) {
        request.proceed()
    }

    /**
     * 用于标注如果权限请求失败，但是用户没有勾选不再询问的时候执行的方法
     */
    private fun onPermissionDenied() {
        Toast.makeText(this, mPermissionRequestEntity!!.showMsg, Toast.LENGTH_SHORT).show()
    }

    /**
     * 当用户选中了授权窗口中的不再询问复选框后并拒绝了权限请求时需要调用的方法，一般可以向用户解释为何申请此权限，并根据实际需求决定是否再次弹出权限请求对话框
     */
    private fun onNeverAskAgain() {
        Toast.makeText(this, mPermissionRequestEntity!!.showMsg, Toast.LENGTH_SHORT).show()
    }

    /**
     * 当用户给予权限时会执行该方法,通知发送方权限已经申请
     */
    private fun requiresPermission() {
        postObject(mPermissionRequestEntity!!.key, mPermissionRequestEntity!!)
    }

    /**
     * 申请位置权限用于打印
     */
    private fun requestBluetoothConnect() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            postObject(
                KeyHelper.PERMISSION_REQUEST_KEY,
                PermissionRequestEntity(
                    key = javaClass.name,
                    showMsg = String.format(
                        resources.getString(R.string.refuse_tip),
                        "蓝牙扫码"
                    ),
                    action = KeyHelper.BLUETOOTH_CONNECT,
                    permissions = arrayOf(
                        Manifest.permission.BLUETOOTH_CONNECT,
                        Manifest.permission.BLUETOOTH_ADVERTISE,
                        Manifest.permission.BLUETOOTH_SCAN,
                    )
                )
            )
        } else {
            mainPageFlutterChannel.invokeMethod(KeyHelper.TO_WMS_METHOD_CHANNEL, null)
        }
    }

    /**
     * 退出断开连接
     */
    override fun onDestroy() {
        super.onDestroy()
        PipeHelper.disconnect()
    }

    /**
     * Flutter引擎初始化时初始化各种消息通道
     */
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        App.flutterEngine = flutterEngine
        androidToFlutterChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "AndroidToFlutter")
        mainPageFlutterChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "MainPageFlutter")
        asOrderPageFlutterChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "AsOrderPageFlutter")
        searchDevicePageChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "SearchDevicePageFlutter")
        deviceDetailPageFlutter = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "DeviceDetailPageFlutter")
        scrollFlutterChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "ScrollIndex")
        dismissChannel = MethodChannel(App.flutterEngine.dartExecutor.binaryMessenger, "flutterUiUpdateChannel")


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.BLUETOOTH_CONNECT
                ) == PERMISSION_GRANTED
            ) {
                BlueConnectStatusListener.setBinaryMessenger()
                sustainCheckConnect()
            }
        } else {
            BlueConnectStatusListener.setBinaryMessenger()
            sustainCheckConnect()
        }

        val messenger = flutterEngine.dartExecutor.binaryMessenger
        // 新建一个 Channel 对象
        val fromFlutterChannel = MethodChannel(messenger, "FlutterToAndroid")
        // 为 channel 设置回调
        fromFlutterChannel.setMethodCallHandler { call, res ->
            // 根据方法名，分发不同的处理
            when (call.method) {
                KeyHelper.CHECK_PERMISSION_RESULT -> {
                    // 获取传入的参数
                    if (ActivityCompat.checkSelfPermission(
                            this,
                            Manifest.permission.BLUETOOTH_CONNECT
                        ) != PERMISSION_GRANTED
                    ) {
                        requestBluetoothConnect()
                    } else {
                        Logger.i("android调用Flutter，调转到WMS主页-KeyHelper.TO_WMS_METHOD_CHANNEL")

                        mainPageFlutterChannel.invokeMethod(KeyHelper.TO_WMS_METHOD_CHANNEL,null)
                    }
                }

                KeyHelper.CHECK_BLUETOOTH_IS_OPEN_4 -> {
                    requestLocationPermissionForPrint(KeyHelper.LOCATION_ACTION_4)
                }

                "registerListener" -> {
                    BlueConnectStatusListener.flutterRegisterListener(call.arguments as String)
                }

                "unbindListener" -> {
                    BlueConnectStatusListener.flutterUnbindListener(call.arguments as String)
                }

                //开始搜索蓝牙设备
                KeyHelper.SEARCH_DEVICE -> searchDevice()

                KeyHelper.DEVICE_INFO -> {
                    val deviceInfo = JSONObject()
                    deviceInfo.put("address",SpUtil.MMKV_mac)
                    deviceInfo.put("name",SpUtil.MMKV_device_name)
                    deviceDetailPageFlutter.invokeMethod(KeyHelper.DEVICE_INFO,deviceInfo.toString())
                }

                KeyHelper.DISSMISS_CONNECT -> {
                    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
                        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PERMISSION_GRANTED) {
                            PipeHelper.disconnect()
                        }
                    }else{
                        PipeHelper.disconnect()
                    }
                }

                //连接指定的蓝牙设备
                KeyHelper.CONNECT_DEVICE -> {
                    val device = mDevices.firstOrNull { it.address == call.arguments }
                    if(device!=null){
                        Thread {
                            PipeHelper.connect(this@MainActivity,device.address, PrinterType.strParsePrinterType(device.name))
                            val isConnect = BlueConnectStatusListener.isConnect()
                            runOnUiThread {
                                searchDevicePageChannel.invokeMethod(KeyHelper.DISS_CONNECT_DIALOG, null)
                                if (isConnect) {
                                    searchDevicePageChannel.invokeMethod(KeyHelper.CONNECT_SUCCESS, getJSONObject(device).toString())
                                } else {
                                    searchDevicePageChannel.invokeMethod(KeyHelper.CONNECT_FAIL, getJSONObject(device).toString())
                                }
                            }
                        }.start()
                    }else{
//                        toast("找不到设备");
                    }
                }

                //打印单张
                KeyHelper.PRINT_SINGLE -> {
                    printSingle(call)
                }

                //打印所有
                KeyHelper.PRINT_ALL -> {
                    printAll(call)
                }

                //停止搜索蓝牙设备
                KeyHelper.STOP_SEARCH_DEVICE -> BluetoothClientUtil.mBluetoothClient.stopSearch()

                else -> {
                    // 如果有未识别的方法名，通知执行失败
                    res.error("error_code", "error_message", null)
                }
            }

        }

    }

    private fun printSingle(call:io.flutter.plugin.common.MethodCall) {
        lifecycleScope.launch {
            var isSend: Boolean
            withContext(context = Dispatchers.IO) {
                val bitmap = getDiskBitmap(call.arguments as String)!!
                val speed = PrinterHelper.Speed("0")
                val contrast = PrinterHelper.Contrast("1")
                Logger.i("打印速度 = $speed,打印浓度 = $contrast")
                val printImage = PrinterHelper.printBitmap(50, 0, 0, bitmap, 0, true, 1)
                isSend = printImage > 0
            }
            Toast.makeText(this@MainActivity,if (isSend) "发送成功" else "发送失败",Toast.LENGTH_SHORT).show()
        }
    }


    private fun printAll(call:io.flutter.plugin.common.MethodCall) {
        val json =  call.arguments as String
        val paths = json.split("|");
        lifecycleScope.launch {
            for (i in paths.indices) {
                var isSend: Boolean
                val path = paths[i]
                dismissChannel.invokeMethod("SLIDING_INDEX", i.toString())
                try {
                    withContext(context = Dispatchers.IO) {
                        delay(1000)
                        val bitmap = getDiskBitmap(path)!!
                        val speed = PrinterHelper.Speed("0")
                        val contrast = PrinterHelper.Contrast("1")
                        Logger.i("打印速度 = $speed,打印浓度 = $contrast")
                        val printImage = PrinterHelper.printBitmap(50, 0, 0, bitmap, 0, true, 1)
                        isSend = printImage > 0
                    }
                    if(!isSend){
//                        toast("标签${item.saleOrderId}打印失败")
                    }
                } catch (e: Exception) {
//                    toast("标签${item.saleOrderId}打印失败，${e.message}")
                } catch (e: TimeoutException) {
//                    toast("标签${item.saleOrderId}打印失败，${e.message}")
                }
            }
            dismissChannel.invokeMethod("DISMISS", null)
        }
    }

    private fun getDiskBitmap(pathString:String):Bitmap?{
         var bitmap:Bitmap? = null;
        try{
             val file = File(pathString);
            if (file.exists()){
                bitmap= BitmapFactory.decodeFile(pathString);
            }
        }catch (e:Exception){
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 添加蓝牙监听
     */
    private fun bluetoothOpenStateListener() {
        BluetoothClientUtil.mBluetoothClient.registerBluetoothStateListener(object :
            BluetoothStateListener() {
            override fun onBluetoothStateChanged(openOrClosed: Boolean) {
                if (openOrClosed) {
                    if(mPermissionRequestEntity != null){
                        androidToFlutterChannel.invokeMethod("bluetoothOpen", null)
                        mPermissionRequestEntity = null
                    }
                } else {
                    BlueConnectStatusListener.notifyDisconnectStatusAll()
                    androidToFlutterChannel.invokeMethod("bluetoothClose", null)
                }
            }

        })
    }

    /**
     * 申请位置权限用于打印
     */
    private fun requestLocationPermissionForPrint(action: Int, any: Any? = null) {
        postObject(
            KeyHelper.PERMISSION_REQUEST_KEY,
            PermissionRequestEntity(
                key = javaClass.name,
                showMsg = String.format(
                    resources.getString(R.string.refuse_tip),
                    getString(R.string.location)
                ),
                action = action,
                permissions = arrayOf(
                    Manifest.permission.ACCESS_FINE_LOCATION,
                ),
                any = any
            )
        )
    }

    /**
     * 搜索设备
     */
    private fun searchDevice() {
        BluetoothClientUtil.mBluetoothClient.stopSearch()
        mDevices.clear()
        val request = SearchRequest.Builder()
            .searchBluetoothClassicDevice(10000)
            .build()
        BluetoothClientUtil.mBluetoothClient.search(request, object : SearchResponse {

            override fun onSearchStarted() {
                mIsShowDeviceList = false
                Logger.i("搜索监听 onSearchStarted")
                //更新左侧标题为搜索中
                searchDevicePageChannel.invokeMethod(KeyHelper.SEARCHING_CHANNEL, null)
            }

            override fun onSearchCanceled() {
                Logger.i("搜索监听 onSearchCanceled")
            }

            override fun onSearchStopped() {
                Logger.i("搜索监听 onSearchStopped")
                if (mDevices.isEmpty()) {
                    //更新左侧标题为搜索并显示失败的视图
                    searchDevicePageChannel.invokeMethod(KeyHelper.DEVICE_NOT_FOUND_CHANNEL, null)
                }
            }

            @SuppressLint("MissingPermission")
            override fun onDeviceFounded(device: SearchResult) {
                Logger.i("搜索监听 onDeviceFounded, " +
                        "设备名称 = ${device.name}, " +
                        "设备地址 =  ${device.address} , " +
                        "设备状态 = ${device.scanRecord}，" +
                        "蓝牙信号 = ${device.rssi}，" +
                        "蓝牙类型 = ${device.device.type}")

                if(device.name.startsWith("DP-230L")){
                    if (device.device.type != BluetoothDevice.DEVICE_TYPE_DUAL) return
                }else{
                    //过滤非经典蓝牙
//                    if (device.device.type != BluetoothDevice.DEVICE_TYPE_DUAL) return
                    if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.R){
                        if (device.device.type != BluetoothDevice.DEVICE_TYPE_CLASSIC) return
                    }else{
                        if (device.device.type != BluetoothDevice.DEVICE_TYPE_DUAL) return
                    }
                }

                //过滤没有信号的设备
                if (device.rssi >= 0) return

                //判断是否在列表中,即搜索到并且有信号的设备是否在列表中
                val isInMachineInfoList = MachineInfoList.find { machineInfo ->
                    device.name.contains(machineInfo.series)
                }

                //假如设备是需要的显示的设备
                if (isInMachineInfoList != null) {
                    val deviceOrNull = mDevices.find {
                        device.name.contains(it.name, true)
                    }
                    if (deviceOrNull == null) {
                        Logger.i("Add Device, 设备名称 = ${device.name}, 设备地址 =  ${device.address} , 设备状态 = ${device.scanRecord}")
                        mDevices.add(device)
                        searchDevicePageChannel.invokeMethod(KeyHelper.ADD_DEVICE_LIST, getJSONObject(device).toString())
                        if (!mIsShowDeviceList) {
                            mIsShowDeviceList = true
                            searchDevicePageChannel.invokeMethod(KeyHelper.SHOW_DEVICE_LIST, null)
                        }
                    }
                }
            }
        })
    }

    fun getJSONObject(device: SearchResult):JSONObject{
        val deviceObject = JSONObject()
        val bluetoothDeviceObject = JSONObject()
        bluetoothDeviceObject.put("name",device.name)
        bluetoothDeviceObject.put("address",device.address)
        deviceObject.put("device",bluetoothDeviceObject)
        deviceObject.put("rssi",device.rssi)
        deviceObject.put("scanRecord",device.scanRecord)
        return deviceObject;
    }

}
